//
//  ReadMe.swift
//  test
//
//  Created by apple on 17/1/16.
//  Copyright © 2017年 apple. All rights reserved.
//

/*
 
- 第三天 
    - 公司人员分配
        - 01 甲方
        - 02 销售 或者老板
        - 03 技术总监 
        - 04 (项目组)项目经理
            - 产品经理 (原型 业务逻辑分析)
            - 攻城师 
                - 苹果
                - 安卓
                - 前端
                - 后台
            - UI设计师
            - 测试攻城师
    - 公司一般
        - 每天早晨有晨会
            - 昨天工作完成情况 
            - 今天工作计划
        - 周五一般下午开会周会
            - 一周完成情况
            - 下周工作计划
 
    - SSH 
        - 客户端 生成私钥和公钥
            - 私钥(RSA密钥)(非对称加密)
        - 把公钥给服务器
        - 每次上传代码
            - 随机生成一个AES密钥(对称加密)
            - 通过AES把项目加密 然后传到服务器
            - 通过RSA密钥给AES密钥加密 然后传送到服务器
        - 服务器接收到后
            - 通过公钥吧加密后的AES 解密 得到AES
            - 通过AES 把加密后的项目解密 
            - 保存项目
 
        ssh-keygen -t rsa -C "smile_faner@163.com"
 
 
    - 第三天上午内容回顾
        - ssh协议 https 
            - 不同点: ssh 需要在客户端生成公钥和私钥
            - https 不要 每次都需要属性用户名和密码 上传代码比较大的时候 会造成失败
        - 开源中国创建项目 
        - 吧远程服务器的项目克隆到本地
        - 添加忽略文件(OC的不需要直接在创建项目的时候就可以选择)
        - 一定要把先忽略文件上传上去
        - 创建新浪微博项目 
            - 最次支持版本
            - 类前缀
            - 设置icon 和启动图
        - 介绍MVVM
            - M model
            - V 
                - view
                - viewController
            - VM viewmodel
        - 创建项目文件夹
            - Model View  ViewModel Tools
        - 创建HMMainVc  
        - 创建HMHomeVc HMMessageVc HMDiscoerVc HMProfileVc
        - 在HMMainVc 创建一个公共方法 (快速创建子子控制器)
        - 自定义HMTabBar -> UIView
            - 类的构造函数 init(frame:)
            - 采用手写代码方式创建 init(coder)
                - 告知类的使用者 当前类只能通过代码的方式创建 不能使用sb xib
            - 懒加载控件 composeButton
            - 设置composeButton Center.x Center.y
            - 重新设置UITabBarButton 是私有的
            - 通过遍历HMTabBar 的子控件数组来完成找到UITabBarButton
            - NSClassFromString("字符串")=AnyClass?
            - 设置UITabBarButton 的frame (w,x)
        - 因为TabBar 是get属性 不能直接赋值
            - 解决方法: 通过kvc完成赋值

 
 
- 第四天
        - OAuth授权
            - open auth 开放的授权
 
        - 开发的app 可以使用手机号 注册 完成登录
                - 也可以通过第三方登录 (微博 微信 QQ 等等)
        - 第三方登录优点
            - 快捷 不需要注册 直接使用第三方的账号登录
            - 安全 (p2p) 
            - 总是受到一些短信或者电话(注册一些app 会把你的个人信息出卖)
 
        - 为什么开发山寨微博 使用微博OAuth授权
            - 我们做的是自己的微博 显示的数据是新浪微博提供的数据
            - 使用新浪微博的数据 就要遵守人家提出来的协议 ->OAuth
 
 
        - 如何才可以获取到新浪微博的数据
            - 注册一个新浪微博账号
            - 登录http://www.open.weibo.com (新浪微博开发者中心)
            - 成为开发者
                - 个人版
                - 企业版 -> 公司
            - 在自己的app中使用新浪微博提供的数据
            - 添加测试账号(在当前app 没有上架之前只有测试账号才可以拿到新浪微博的数据) 上架以后 只要使用当前app的使用者均可以访问新浪微博的数据
            - 在开发者中心注册一个应用 告知当前应用要使用微博数据
                - 新浪微博就会返回一些信息
                        - APPKEY
                        - APPSECRECT
                - 为我们获取code (授权码) token(访问令牌)
            - 在我们的app中加载webView (微博授权登录界面)
            - 确认授权
            - 获取code
            - 通过code 获取 token
            - 以后请求新浪微博数据 均是通过token 获取到当前账号的微博数据
 
 
 
    - 第五天下午内容回顾
        - HMOAuthViewModel中添加属性
            - userAccountModel(不想重复调用沙盒)
            - accessToken (因为一般我们后期使用的请求都会使用当前token)
            - isLogin (AppDelegate中需要判断根控制器 和 visitorVc中需要判断是否登录)
        - 因为HMOAuthViewModel 会给很多类提供个人信息数据 防止多次创建
            - 解决办法 -> 变成一个单例
        - 欢迎界面的开发
            - 背景图片
            - 头像
            - 文字
            - 使用阻尼动画设置头像
                - 使用更新约束
                - 使用self.view.layoutIfNeeded
        - 切换根控制
            - 如果首次登陆app
                - 访客视图界面 -> 微博登录界面 -> 欢迎界面 -> 首页
            - 如果你已经登录过了
                - 欢迎界面 -> 首页
 
        - 当app登录时候 根控制器的选择
            - 如果登录了 -> HMWelcomeVc
            - 如果没有登录 -> HMMainVc
 
        - 对SDWebImage 进行了封装
        - 抽取UILabel的extension   
        - 定义常用文字大小常量
 
 
 
     - 第六天上午内容回顾
        - 加载首页数据
            - 返回的数据最外层是字典
            - 需要通过key 获取到value -> 数组(每个元素是字典) -> 使用列表显示
            - 创建首页对应的模型 HMHomeModel -> 数组 转成乘载模型的数组 -> YYModel 
        - 简单的使用系统的tableViewCell 显示一下 看下效果
        - 对HomeVc的代码进行抽取
            - 是吧HomeVc的网络请求抽取到HMNetworkTools中 -> 请求的url 请求的参数全部分装到HMNetworkTools
            - 是把HMNetworkTools首页对应的的网络请求抽取到HMHomeViewModel中
                - HMHomeViewModel 作用 (MVVM开发)
                    - 帮助HomeVc 请求数据 -> 导致HomeVc 只需要接受成功或者失败的最终情况
                    - 给HomeVc提供数据 -> HomeVc 使用数据 需要找HomeViewModel要
        - 对首页自定义cell 进行分析 -> 布局
            - 原创微博
                - 头像
                - 昵称
                - 会员等级
                - 时间
                - 来源
                - 认证
                - 内容
                - 配图 -> 可能有可能没有*
            - 转发微博 -> 可能有可能没有*
                - 内容
                - 配图 -> 可能有可能没有*
            - 底部视图
                - 转发评论赞 三个按钮
        - 自定义原创微博 进行原创微博的UI搭建
 
 
        - 什么时候直接通过属性的点语法获取对应的值 -> 不需要程序员处理
            - 答 结果可以直接使用的
        - 什么时候通过ViewModel 获取对应的处理后的新属性 -> 需要程序员处理
            - 答 通过业务逻辑处理后才可以显示最终结果的
 
 
 
     - 第七天上午内容回顾
        - 转发微博
            - 每个cell 可能有转发微博 也可能没有
            - 通过什么来判断是否有转发微博
                - homeModel.retweet_status 是否为nil 
                    != nil  有
                    == nil  没有
                - 学习了什么技术
                    - 因为每个cell中的底部视图的顶部约束 的约束对象发生了改变
                        - 可能是转发微博 
                        - 也可能是原创微博
                        - 解决问题: 
                            - 记录底部视图的顶部约束
                            - 在didSet方法中 先卸载约束
                            - 然后重新设置约束
                                - 重新设置约束也不要忘记记录约束
                    - cell重用问题
                        - 不管你有没有转发微博 我通过转发微博是否存在来设置转发视图是否显示
            - 给原创微博添加配图控件 -> UICollectionView
                    - 判断是否有配图 
                        - 通过homeModel.pic_urls -> 数组(HMPictureModel)
                            - 是一个数组我们使用的yymodel 通过容器转模型
                                - 通过一个类方法modelContainerPropertyGenericClass
                        - 如果pic_urls.count > 0 就代表有配图 反之没有配图
                            -cell 重用问题 通过是否有配图 是否显示配图
                            - 约束问题 记录约束和卸载约束 -> 因为约束的相对对象发生了改变
 
            - 用过图片的张数来计算配图控件的大小
                    - 如果不等于4张 最多可以显示9张  九宫格
                    - 如果是4张 2*2
                    - 使用 SnapKit update 更新约束 -> 适用于相对的对象没有发生改变
            - 自定义配图cell
                    - 背景图片  
                        - 图片的填充方式
 
 
 
        - 第七天下午
                - 单张图片显示的业务路基介绍
                 - 假设原创微博 或者是转发微博 他可能有图片
                 - 假设他肯定有图片 count > 1 <= 9
                 - 如果他就是一张图片
                         你原来的图片多大就显示多大
                         - 如果你原来的图片宽度 小于80 那么你就显示80
                         - 如果你原来的图片高度大约150 那么你就显示150
                         - 假设我们的图片是80*150
                         - 配图collectionView 的size 编程 80*150
 
                - 解决方案
                    - 在我们请求首页数据的时候 当数据返回来以后
                        - 判断返回来的(homeModel|| homeModel.retweet_stauts)中的pic_urls.count == 1
                            下载图片
                        - 但监听到单张图片全部下载完成后 我们在告知控制器刷新
 
 
            - 分析新浪微博首页下拉刷新和上拉加载更过的逻辑
                since_id  -> 下拉刷新
                max_id    -> 上拉加载更过
                
 
            - 如果默认请求回来的微博id 分别是 10 9 8 7 6
                - 如果是下拉刷新
                    - since_id = 10 返回比10大的微博数据
                - 如果是上拉加载更过
                    - max_id = 6 - 1 返回我们需要的数据
 
                - 模型保存在dataArray中
                        since_id = dataArray.first.id
                        max_id = dataArray.last.id - 1
 
 
    - 第八天
        - 自定义下拉刷新控件分析
            - 使用什么自定义 
                    - UIControl
            - 添加到谁身上
                    - UITableView
            - 控件的Y轴 
                    - -控件高度
        - 自定义刷新控件拥有的状态(三种状态)(显示的效果 -> UILabel)
            - 正常中
            - 下拉中
            - 刷新中
        - 如果知道当前设置为什么状态(在我们滑动列表的时候状态发生改变的)
        - 通过监听列表的什么变化 来改变自定义刷新控件的状态
            - 通过监听ContentOffset.Y
        - 在那个类中监听ContentOffset.Y 来改变状态
            - 在HMRefreshControl中监听
        - 在HMRefreshControl 中如果监听UITabelView的ContentOffset.Y 的变化
            - 代理 -> 否定 (代理是一对一)
            - KVO (一对多)
 
        - 关于偏移量问题
            - 如果Y < - 114  -> 下拉中
            - 如果Y >= -114  -> 正常中
            - 必须当前的状态为 下拉中 而且用户必须在这个时候松手  -> 刷新中
            - 如果用户没有松手 返回拖动中 有几种状态
                - 正常中 和下拉中
 
            - 优化逻辑
                01- 判断用户是否在拖动列表而且是否松手
                    - 如果没有松手
                        - 正常和下拉中
                             - 如果Y < - 114 && 当前的状态为正常中 -> 下拉中
                             - 如果Y >= -114 && 当前的状态为下拉中 -> 正常中
                    - 如果用户松手了
                            - 如果当前的状态为下拉中 -> 刷新中
 
 
 
    - 第十天
        - 自定义表情数据结果分析
 
            分为几种表情
                - 最近(一页) [[20]]
                    [20]
                - 默认(六页) 108 [[20] [20] [20] [20] [20] [8]]
                    [20] [20] [20] [20] [20] [8]
                - emoji(四页) 80 [[20] [20] [20] [20]]
                    [20] [20] [20] [20]
                - 浪小花 (两页) 40 [[20] [20]]
                    [20] [20]
 
 
 
 
        - 分析collectionView ()
                -分为四组 最近 默认 emoji 浪小花
                    - 最近
                        - 一页
                    - 默认
                        - 六页
                    - emoji
                        - 四页
                    - 浪小花
                        - 两页
                - collectionView 通过什么确定的组的个数
                [[[20]],[[20] [20] [20] [20] [20] [8]],[[20] [20] [20] [20]],[[20] [20]]].count == 4
 
 
    - 第十二天
            - 例如 首页显示 文字为 A[马到成功]A
                    -最终显示的效果 A表情A
                        
                - 解决方案 
                    - 在首页的文字中找到对应的图片描述  
                    - 通过描述在本地的图片表情数组中 得到相应的模型
                    - 通过模型中的图片名 png
                    - 通过png 得到对应的image
                    - 通过image 创建一个文本附件
                    - 通过文本附件创建一个不可变的富文本
                    - 在吧首页文字的内容变成一个可变的富文本
                    - 在通过图片描述的位置得到范围 range
                    - 在使用可变的富文本替换range的范围的内容为不可变的富文本
 
 
            - 为什么越界
                AA[哈哈]AA[嘻嘻]
                [哈哈] range (2,4) 结果 AA表AA[嘻嘻]
                [嘻嘻] range (8,4)
                -解决办法
                [嘻嘻] range (8,4) AA[哈哈]AA表
                [哈哈] range (2,4) AA表AA表
 
 
        - 微博首页数据缓存 数据库表结构分析
                - 数据库中 需要 设计多个个字段(属性)
                    - userid (区分那个用户缓存的数据)
                    - status (需要把从网络请求回来的数据全部保存 防止后期需求发生改变需要重新设计数据库)
                    - statusid (为了用户查询本地数据的时候有一个条件(下拉刷新还是上拉加载更多))
                    - createtime (计算本条微博数据是什么时间插入到数据库中 便于后期清理垃圾数据)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 */
